﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using GameCamera;

namespace Light
{
  public class LightPoint
  {
    Vector4 ambientColor;
    float ambientIntensity;
    Vector4 diffuseColor;
    float diffuseIntensity;
    Vector3 diffusePos, target, lightDir;
    Vector4 specularColor;
    float angle;
    Effect lightingEffect;
    Camera camera;
    EffectParameter ambientColorParam, ambientIntensityParam;
    EffectParameter diffuseColorParam, diffuseIntensityParam, diffuseDirectionParam;
    EffectParameter specularColorParam, viewPointParam, lightWorldParam, floorTextureParam;
    Matrix lightView, lightProjection;
    bool rotating;

    public Vector4 DiffuseColor
    {
      get { return diffuseColor; }
    }

    public float DiffuseIntensity
    {
      get { return diffuseIntensity; }
    }

    public Vector3 DiffusePos
    {
      get { return diffusePos; }
    }

    public Vector4 SpecularColor
    {
      get { return specularColor; }
    }

    public Effect LightingEffect
    {
      get { return lightingEffect; }
      set { lightingEffect = value; }
    }

    public bool Rotate
    {
      get { return rotating; }
      set { rotating = value; }
    }

    public Matrix lightProjectionMatrix
    {
      get
      {
        return lightView * lightProjection;
      }
    }

    public LightPoint(Camera camera, Effect lightingEffect, Vector4 diffuseColor, float diffuseIntensity,
        Vector3 pos, Vector4 specularColor, Vector3 lightTarget, TextureCube floorTexture)
    {
      this.diffuseColor = diffuseColor;
      this.diffuseIntensity = diffuseIntensity;
      this.diffusePos = pos;
      this.specularColor = specularColor;
      this.ambientColor = Color.White.ToVector4();//new Color(0.2f, 0.2f, 0.2f, 255.0f).ToVector4();
      this.ambientIntensity = 0.25f;
      this.lightingEffect = lightingEffect;
      this.target = lightTarget;
      this.lightDir = pos - lightTarget;
      angle = 0.0f;
      this.camera = camera;
      Vector3 diffuseLightDirection = this.diffusePos;
      diffuseLightDirection.Normalize();
      ambientColorParam = lightingEffect.Parameters["AmbientColor"];
      ambientIntensityParam = lightingEffect.Parameters["AmbientIntensity"];
      diffuseColorParam = lightingEffect.Parameters["DiffuseColor"];
      diffuseIntensityParam = lightingEffect.Parameters["DiffuseIntensity"];
      diffuseDirectionParam = lightingEffect.Parameters["DiffuseDirection"];
      specularColorParam = lightingEffect.Parameters["SpecularColor"];
      viewPointParam = lightingEffect.Parameters["EyePosition"];
      lightWorldParam = lightingEffect.Parameters["LightsWorldViewProjection"];
      floorTextureParam = LightingEffect.Parameters["FloorTexture"];
      ambientColorParam.SetValue(this.ambientColor);
      ambientIntensityParam.SetValue(this.ambientIntensity);
      diffuseColorParam.SetValue(this.DiffuseColor);
      diffuseIntensityParam.SetValue(this.DiffuseIntensity);
      diffuseDirectionParam.SetValue(diffuseLightDirection);
      specularColorParam.SetValue(this.SpecularColor);
      floorTextureParam.SetValue(floorTexture);
      viewPointParam.SetValue(camera.Position);
      Vector3 lightForward = Vector3.Normalize(lightTarget - pos);
      Vector3 lightUp = Vector3.Normalize(Vector3.Up - lightForward * Vector3.Up * lightForward);
      lightView = Matrix.CreateLookAt(pos, lightTarget, Vector3.Up);
      lightProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.Pi / 3.0f, 1f, 32.0f, 150.0f);
      lightWorldParam.SetValue(Matrix.Identity * this.lightProjectionMatrix);
    }

    public void Update()
    {

      Vector3 diffuseLightDirection = this.diffusePos;
      diffuseLightDirection.Normalize();
      viewPointParam.SetValue(camera.Position);
      diffuseDirectionParam.SetValue(diffuseLightDirection);
      lightView = Matrix.CreateLookAt(diffusePos, target, Vector3.Up);
      lightProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.Pi / 3.0f, 1f, 32.0f, 150.0f);
      lightWorldParam.SetValue(Matrix.Identity * this.lightProjectionMatrix);
      if (rotating)
        rotate();
    }


    private void rotate()
    {
      const float ROTATION_SPEED = 0.04f;
      //angle += ROTATION_SPEED;
      diffusePos = Vector3.Transform(diffusePos, Matrix.CreateRotationY(ROTATION_SPEED));
    }
  }
}
